﻿// Note that all summaries can be documented here, since the user will always be working with the interface rather than the implementation

namespace Webinator
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Drawing;
    using Enums;
    using HtmlAgilityPack;
    using Impls;
    using Interfaces;
    using Util;

    using Webinator.DomTraversal;

    /// <summary>
    /// The main interface to implement all expected functionality.
    /// </summary>
    public interface IWebManager
    {
        /// <summary>
        /// Gets or sets the configuration.
        /// </summary>
        Config Config { get; set; }

        /// <summary>
        /// Gets the DOM of the page.
        /// </summary>
        DomNode Dom { get; }

        /// <summary>
        /// Gets or sets the log.
        /// </summary>
        ILogUtil Log { get; set; }

        /// <summary>
        /// Gets or sets the process associated with this instance of <c>IWebManager</c>.
        /// </summary>
        Process Process { get; set; }

        /// <summary>
        /// Gets or sets the viewport X and Y.
        /// </summary>
        Point ViewportCoordinates { get; set; }

        /// <summary>
        /// Gets or sets the viewport dimensions.
        /// </summary>
        Size ViewportDimensions { get; set; }

        /// <summary>
        /// Gets or sets the window state (normal, minimized, maximized).
        /// </summary>
        WindowHelper.WindowState WindowState { get; set; }

        /// <summary>
        /// Adds a cookie to the session.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        /// <param name="path">The path.</param>
        /// <param name="domain">The domain.</param>
        /// <returns>The current web manager instance.</returns>
        IWebManager AddCookie(string name, string value, string path, string domain);

        /// <summary>
        /// Appends the specified text/keystrokes to an element.
        /// </summary>
        /// <param name="locator">The element location.</param>
        /// <param name="text">The text.</param>
        /// <param name="condition">The condition.</param>
        /// <returns>The current web manager instance.</returns>
        IWebManager AppendText(Locator locator, string text, ICondition condition = null);

        /// <summary>
        /// Navigates the browser back.
        /// </summary>
        /// <returns>The current web manager instance.</returns>
        IWebManager Back();

        /// <summary>
        /// Clears the text of the specified element.
        /// </summary>
        /// <param name="locator">The element location.</param>
        /// <param name="condition">The condition.</param>
        /// <returns>The current web manager instance.</returns>
        IWebManager Clear(Locator locator, ICondition condition = null);

        /// <summary>
        /// Clicks on the specified element.
        /// </summary>
        /// <param name="locator">The element location.</param>
        /// <param name="condition">The condition.</param>
        /// <returns>The current web manager instance.</returns>
        IWebManager Click(Locator locator, ICondition condition = null);

        /// <summary>
        /// Clicks on the specified element.
        /// </summary>
        /// <param name="locator">The element location.</param>
        /// <param name="expectAlert">If you expect the click action to trigger an alert, set this to true.</param>
        /// <param name="condition">The condition.</param>
        /// <returns>The current web manager instance.</returns>
        IWebManager Click(Locator locator, bool expectAlert, ICondition condition = null);

        /// <summary>
        /// Closes the browser.
        /// </summary>
        void CloseBrowser();

        /// <summary>
        /// Closes the current popup.
        /// </summary>
        /// <returns>The current web manager instance.</returns>
        IWebManager CloseCurrentWindow();

        /// <summary>
        /// Confirms the current dialog.
        /// </summary>
        /// <returns>The current web manager instance.</returns>
        IWebManager ConfirmDialog();

        /// <summary>
        /// Removes a cookie from the session.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns>The current web manager instance.</returns>
        IWebManager DeleteCookie(string name);

        /// <summary>
        /// Dismisses the current dialog.
        /// </summary>
        /// <returns>The current web manager instance.</returns>
        IWebManager DismissDialog();

        /// <summary>
        /// Displays the specified message in the browser.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="timeoutInMilliseconds">
        /// The timeout in milliseconds.
        /// </param>
        /// <returns>The current web manager instance.</returns>
        IWebManager DisplayMessageInBrowser(string message, int timeoutInMilliseconds = 2000);

        /// <summary>
        /// Executes the specified javascript.
        /// </summary>
        /// <param name="js">
        /// The javascript to execute.
        /// </param>
        /// <returns>
        /// The javascript result.
        /// </returns>
        object EvalJavaScript(string js);

        /// <summary>
        /// Determines whether the specified element exists on the current page.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <param name="timeoutInMilliseconds">
        /// The timeout in milliseconds.
        /// </param>
        /// <returns>
        /// A boolean value indicating whether the specified element is found on the current page.
        /// </returns>
        bool Exists(Locator locator, int timeoutInMilliseconds = 5000);

        /// <summary>
        /// Navigates the browser forward.
        /// </summary>
        /// <returns>The current web manager instance.</returns>
        IWebManager Forward();

        /// <summary>
        /// Gets the specified attribute.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <param name="attribute">
        /// The attribute.
        /// </param>
        /// <returns>
        /// The value of the attribute.
        /// </returns>
        string GetAttribute(Locator locator, string attribute);

        /// <summary>
        /// Gets the underlying framework.
        /// </summary>
        /// <returns>
        /// The underlying framework.
        /// </returns>
        object GetEngine();

        /// <summary>
        /// Calculates the location of the specified element within the viewport.
        /// </summary>
        /// <param name="locator">The locator.</param>
        /// <returns>
        /// A <c>Rectangle</c> containing the x, y, width, and height of the element.
        /// </returns>
        Rectangle GetLocatorLocation(Locator locator);

        /// <summary>
        /// Calculates the location of the specified elements within the viewport.
        /// </summary>
        /// <param name="locator">The locator.</param>
        /// <returns>
        /// A collection of <c>Rectangle</c>s containing the x, y, width, and height of each element.
        /// </returns>
        IEnumerable<Rectangle> GetLocatorLocations(Locator locator);

        /// <summary>
        /// Counts the number of nodes found at the specified location.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <returns>
        /// The number of nodes found.
        /// </returns>
        int GetNodeCount(Locator locator);

        /// <summary>
        /// Retrieves the Html nodes found at the specified location.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <returns>
        /// A collection of Html Nodes.
        /// </returns>
        HtmlNodeCollection GetHtmlNodes(Locator locator);

        /// <summary>
        /// Retrieves the selected item from the collection.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <returns>
        /// The selected item.
        /// </returns>
        SelectedItem GetSelectedElementFromCollection(Locator locator);

        /// <summary>
        /// Retrieves the selected items from the collection.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <returns>
        /// The selected items.
        /// </returns>
        IEnumerable<SelectedItem> GetSelectedElementsFromCollection(Locator locator);

        /// <summary>
        /// Retrieves the selected list item.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <returns>
        /// The selected item.
        /// </returns>
        SelectedItem GetSelectedListItem(Locator locator);

        /// <summary>
        /// Retrieves the selected list items.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <returns>
        /// The selected items.
        /// </returns>
        IEnumerable<SelectedItem> GetSelectedListItems(Locator locator);

        /// <summary>
        /// Gets the text of the specified element.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <returns>
        /// The text.
        /// </returns>
        string GetText(Locator locator);

        /// <summary>
        /// Navigates to the specified url.
        /// </summary>
        /// <param name="url">
        /// The url.
        /// </param>
        /// <param name="condition">
        /// The condition.
        /// </param>
        /// <returns>The current web manager instance.</returns>
        IWebManager GoToUrl(string url, ICondition condition = null);

        /// <summary>
        /// Highlights the specified element.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <param name="removeHighlight">
        /// If set to <c>true</c>, removes the highlight rather than adding it.
        /// </param>
        /// <returns>The current web manager instance.</returns>
        IWebManager Highlight(Locator locator, bool removeHighlight = false);

        /// <summary>
        /// Retrieves the html source of the current page.
        /// </summary>
        /// <returns>
        /// The html source of the current page, as an <c>HtmlDocument</c>.
        /// </returns>
        HtmlDocument HtmlSource();

        /// <summary>
        /// Determines whether the specified element is selected.
        /// </summary>
        /// <param name="locator">The locator.</param>
        /// <returns>
        /// A boolean value indicating whether the specified element is selected.
        /// </returns>
        bool IsSelected(Locator locator);

        /// <summary>
        /// Determines whether the specified element is visible on the current page.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <param name="timeoutInMilliseconds">
        /// The timeout in milliseconds.
        /// </param>
        /// <returns>
        /// A boolean value indicating whether the specified element is visible on the current page.
        /// </returns>
        bool IsVisible(Locator locator, int timeoutInMilliseconds = 5000);

        /// <summary>
        /// Maximizes the browser size on the screen.
        /// </summary>
        /// <returns>The current web manager instance.</returns>
        IWebManager MaximizeScreen();

        /// <summary>
        /// Retrieves the html source of the current page.
        /// </summary>
        /// <returns>
        /// The html source of the current page as a string.
        /// </returns>
        string PageSource();

        /// <summary>
        /// Refreshes the current page.
        /// </summary>
        /// <returns>The current web manager instance.</returns>
        IWebManager Refresh();

        /// <summary>
        /// Executes the specified javascript.
        /// </summary>
        /// <param name="js">
        /// The js.
        /// </param>
        /// <returns>The current web manager instance.</returns>
        IWebManager RunJavaScript(string js);

        /// <summary>
        /// Checks or unchecks the specified checkbox.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <param name="check">
        /// The check.
        /// </param>
        /// <param name="condition">
        /// The condition.
        /// </param>
        /// <returns>
        /// The current web manager instance.
        /// </returns>
        IWebManager SelectCheckbox(Locator locator, bool check, ICondition condition = null);

        /// <summary>
        /// Selects the specified list items.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <param name="selectors">
        /// The selectors.
        /// </param>
        /// <returns>
        /// The current web manager instance.
        /// </returns>
        IWebManager SelectListItem(Locator locator, params Selector[] selectors);
        
        /// <summary>
        /// Selects the specified list items.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <param name="condition">The condition.</param>
        /// <param name="selectors">
        /// The selectors.
        /// </param>
        /// <returns>
        /// The current web manager instance.
        /// </returns>
        IWebManager SelectListItem(Locator locator, ICondition condition, params Selector[] selectors);

        /// <summary>
        /// Selects the specified radio button.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <param name="condition">
        /// The condition.
        /// </param>
        /// <returns>
        /// The current web manager instance.
        /// </returns>
        IWebManager SelectRadio(Locator locator, ICondition condition = null);

        /// <summary>
        /// Sends the specified text/keystrokes to an element.
        /// </summary>
        /// <param name="locator">The element location.</param>
        /// <param name="text">The text.</param>
        /// <param name="condition">The condition.</param>
        /// <returns>The current web manager instance.</returns>
        IWebManager SendKeys(Locator locator, string text, ICondition condition = null);

        /// <summary>
        /// Sets the specified attribute.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <param name="attribute">
        /// The attribute.
        /// </param>
        /// <param name="value">The value.</param>
        /// <returns>The current web manager instance.</returns>
        IWebManager SetAttribute(Locator locator, string attribute, string value);

        /// <summary>
        /// Sets the browser to the specified dimensions.
        /// </summary>
        /// <param name="width">
        /// The width.
        /// </param>
        /// <param name="height">
        /// The height.
        /// </param>
        /// <returns>The current web manager instance.</returns>
        IWebManager SetResolution(int width, int height);

        /// <summary>
        /// Sets the "value" attribute of the element to the specified text.
        /// </summary>
        /// <param name="locator">The element location.</param>
        /// <param name="text">The text.</param>
        /// <returns>The current web manager instance.</returns>
        IWebManager SetText(Locator locator, string text);

        /// <summary>
        /// Switches to the specified popup window.
        /// </summary>
        /// <param name="switchBy">
        /// How to find the popup window to switch to.
        /// </param>
        /// <param name="comparison">Indicates how to match the <c>argument</c>.</param>
        /// <param name="argument">
        /// The argument.
        /// </param>
        /// <returns>The current web manager instance.</returns>
        IWebManager SwitchToWindow(SwitchBy switchBy, Comparison comparison, string argument);

        /// <summary>
        /// Switches to the main window.
        /// </summary>
        /// <returns>The current web manager instance.</returns>
        IWebManager SwitchToMainWindow();

        /// <summary>
        /// Switches to the specified frame.
        /// </summary>
        /// <param name="locator">The locator.</param>
        /// <returns>The current web manager instance.</returns>
        IWebManager SwitchToFrame(Locator locator);

        /// <summary>
        /// Switches to the default frame.
        /// </summary>
        /// <returns>The current web manager instance.</returns>
        IWebManager SwitchToMainFrame();

        /// <summary>
        /// Takes a screenshot of the browser.
        /// </summary>
        /// <param name="filename">
        /// The filename.
        /// </param>
        /// <returns>The current web manager instance.</returns>
        IWebManager TakeScreenShot(string filename);

        /// <summary>
        /// Determines if the specified text is present in the browser.
        /// </summary>
        /// <param name="text">
        /// The text.
        /// </param>
        /// <returns>
        /// <c>True</c> if the text is present in the browser, otherwise <c>false</c>.
        /// </returns>
        bool TextPresent(string text);

        /// <summary>
        /// Retrieves the title of the current page.
        /// </summary>
        /// <returns>
        /// The title of the current page.
        /// </returns>
        string Title();

        /// <summary>
        /// Triggers the specified event on the element.
        /// </summary>
        /// <param name="locator">
        /// The locator.
        /// </param>
        /// <param name="eventIs">
        /// The type of event to trigger.
        /// </param>
        /// <param name="condition">
        /// The condition.
        /// </param>
        /// <returns>The current web manager instance.</returns>
        IWebManager TriggerEvent(Locator locator, EventIs eventIs, ICondition condition = null);

        /// <summary>
        /// Retrieves the url of the current page.
        /// </summary>
        /// <returns>
        /// The url of the current page.
        /// </returns>
        string Url();

        /// <summary>
        /// Retrieves all visible text in the browser.
        /// </summary>
        /// <returns>
        /// All visible text in the browser.
        /// </returns>
        string VisibleText();

        /// <summary>
        /// Waits until the specified condition(s) are true.
        /// </summary>
        /// <param name="condition">The condition.</param>
        /// <returns>
        /// <c>False</c> if the wait failed, <c>True</c> if it succeeded.
        /// </returns>
        bool Wait(ICondition condition);

        /// <summary>
        /// Performs the action and waits until the specified condition(s) are true.
        /// </summary>
        /// <param name="action">
        /// The action.
        /// </param>
        /// <param name="condition">
        /// The condition.
        /// </param>
        /// <returns>
        /// <c>False</c> if the wait failed, <c>True</c> if it succeeded.
        /// </returns>
        bool Wait(Action action, ICondition condition);
    }
}